﻿#region Using directives
using System;
using System.Globalization;
using System.Text;
#endregion

namespace Blazorise.AntDesign
{
    public class AntDesignThemeGenerator : ThemeGenerator
    {
        #region Constructors

        public AntDesignThemeGenerator( IThemeCache themeCache )
            : base( themeCache )
        {
        }

        #endregion

        #region Methods

        protected override void GenerateBackgroundVariantStyles( StringBuilder sb, Theme theme, string variant )
        {
            sb.Append( $".bg-{variant}" ).Append( "{" )
                .Append( $"background-color: {Var( ThemeVariables.BackgroundColor( variant ) )} !important;" )
                .AppendLine( "}" );

            sb.Append( $".ant-hero-{variant}" ).Append( "{" )
                .Append( $"background-color: {Var( ThemeVariables.BackgroundColor( variant ) )} !important;" )
                .Append( $"color: {ToHex( Contrast( theme, Var( ThemeVariables.BackgroundColor( variant ) ) ) )} !important;" )
                .AppendLine( "}" );
        }

        protected override void GenerateBorderVariantStyles( StringBuilder sb, Theme theme, string variant )
        {
            sb.Append( $".ant-border-{variant}" ).Append( "{" )
                .Append( $"border-color: {Var( ThemeVariables.BackgroundColor( variant ) )} !important;" )
                .AppendLine( "}" );
        }

        protected override void GenerateButtonVariantStyles( StringBuilder sb, Theme theme, string variant, ThemeButtonOptions options )
        {
            var background = Var( ThemeVariables.ButtonBackground( variant ) );
            var border = Var( ThemeVariables.ButtonBorder( variant ) );
            var hoverBackground = Var( ThemeVariables.ButtonHoverBackground( variant ) );
            var hoverBorder = Var( ThemeVariables.ButtonHoverBorder( variant ) );
            var activeBackground = Var( ThemeVariables.ButtonActiveBackground( variant ) );
            var activeBorder = Var( ThemeVariables.ButtonActiveBorder( variant ) );
            var yiqBackground = Var( ThemeVariables.ButtonYiqBackground( variant ) );
            var yiqHoverBackground = Var( ThemeVariables.ButtonYiqHoverBackground( variant ) );
            var yiqActiveBackground = Var( ThemeVariables.ButtonYiqActiveBackground( variant ) );
            var boxShadow = Var( ThemeVariables.ButtonBoxShadow( variant ) );

            sb.Append( $".ant-btn-{variant}" ).Append( "{" )
                .Append( $"color: {yiqBackground} !important;" )
                .Append( GetGradientBg( theme, background, options?.GradientBlendPercentage, true ) )
                .Append( $"border-color: {border} !important;" )
                .AppendLine( "}" );

            sb.Append( $".ant-btn-{variant} > a:only-child" ).Append( "{" )
                .Append( "color: currentColor !important;" )
                .AppendLine( "}" );

            sb.Append( $".ant-btn-{variant}:hover," )
                .Append( $".ant-btn-{variant}:focus" )
                .Append( "{" )
                .Append( $"color: {yiqHoverBackground} !important;" )
                .Append( GetGradientBg( theme, hoverBackground, options?.GradientBlendPercentage, true ) )
                .Append( $"border-color: {hoverBorder} !important;" )
                .AppendLine( "}" );

            sb.Append( $".ant-btn-{variant}:hover > a:only-child," )
                .Append( $".ant-btn-{variant}:focus > a:only-child" )
                .Append( "{" )
                .Append( "color: currentColor !important;" )
                .AppendLine( "}" );

            sb
                .Append( $".btn-{variant}:active," )
                .Append( $".btn-{variant}.active," )
                .Append( $".btn-{variant}-active" )
                .Append( "{" )
                .Append( $"color: {yiqActiveBackground} !important;" )
                .Append( $"background-color: {activeBackground} !important;" )
                .Append( $"border-color: {activeBorder} !important;" )
                .AppendLine( "}" );

            sb
                .Append( $".btn-{variant}:active > a:only-child," )
                .Append( $".btn-{variant}.active > a:only-child," )
                .Append( $".btn-{variant}-active > a:only-child" )
                .Append( "{" )
                .Append( "color: currentColor !important;" )
                .AppendLine( "}" );

            sb
                .Append( $".ant-btn-{variant}-disabled," )
                .Append( $".ant-btn-{variant}.disabled," )
                .Append( $".ant-btn-{variant}[disabled]," )
                .Append( $".ant-btn-{variant}-disabled:hover," )
                .Append( $".ant-btn-{variant}.disabled:hover," )
                .Append( $".ant-btn-{variant}[disabled]:hover," )
                .Append( $".ant-btn-{variant}-disabled:focus," )
                .Append( $".ant-btn-{variant}.disabled:focus," )
                .Append( $".ant-btn-{variant}[disabled]:focus," )
                .Append( $".ant-btn-{variant}-disabled:active," )
                .Append( $".ant-btn-{variant}.disabled:active," )
                .Append( $".ant-btn-{variant}[disabled]:active," )
                .Append( $".ant-btn-{variant}-disabled.active," )
                .Append( $".ant-btn-{variant}.disabled.active," )
                .Append( $".ant-btn-{variant}[disabled].active" )
                .Append( $".btn-{variant}:disabled" )
                .Append( "{" )
                .Append( "color: rgba(0, 0, 0, 0.25) !important;" )
                .Append( "background-color: #f5f5f5 !important;" )
                .Append( "border-color: #d9d9d9 !important;" )
                .Append( "text-shadow: none !important;" )
                .AppendLine( "}" );

            sb
                .Append( $".ant-btn-{variant}-disabled > a:only-child," )
                .Append( $".ant-btn-{variant}.disabled > a:only-child," )
                .Append( $".ant-btn-{variant}[disabled] > a:only-child," )
                .Append( $".ant-btn-{variant}-disabled:hover > a:only-child," )
                .Append( $".ant-btn-{variant}.disabled:hover > a:only-child," )
                .Append( $".ant-btn-{variant}[disabled]:hover > a:only-child," )
                .Append( $".ant-btn-{variant}-disabled:focus > a:only-child," )
                .Append( $".ant-btn-{variant}.disabled:focus > a:only-child," )
                .Append( $".ant-btn-{variant}[disabled]:focus > a:only-child," )
                .Append( $".ant-btn-{variant}-disabled:active > a:only-child," )
                .Append( $".ant-btn-{variant}.disabled:active > a:only-child," )
                .Append( $".ant-btn-{variant}[disabled]:active > a:only-child," )
                .Append( $".ant-btn-{variant}-disabled.active > a:only-child," )
                .Append( $".ant-btn-{variant}.disabled.active > a:only-child," )
                .Append( $".ant-btn-{variant}[disabled].active" )
                .Append( $".btn-{variant}:disabled" )
                .Append( "{" )
                .Append( "color: currentColor !important;" )
                .AppendLine( "}" );

            if ( options?.DisabledOpacity != null )
                sb.Append( $".ant-btn-{variant}[disabled]" ).Append( "{" )
                    .Append( $"color: rgba(0, 0, 0, {options.DisabledOpacity}) !important;" )
                    .AppendLine( "}" );
        }

        protected override void GenerateButtonOutlineVariantStyles( StringBuilder sb, Theme theme, string variant, ThemeButtonOptions options )
        {
            var color = Var( ThemeVariables.OutlineButtonColor( variant ) );
            var hoverColor = Var( ThemeVariables.OutlineButtonHoverColor( variant ) );
            var activeColor = Var( ThemeVariables.OutlineButtonActiveColor( variant ) );

            sb.Append( $".ant-btn-outline-{variant}" ).Append( "{" )
                .Append( $"color: {color} !important;" )
                .Append( "background: transparent !important;" )
                .Append( $"border-color: {color} !important;" )
                .AppendLine( "}" );

            sb.Append( $".ant-btn-outline-{variant} > a:only-child" ).Append( "{" )
                .Append( "color: currentColor !important;" )
                .AppendLine( "}" );

            sb.Append( $".ant-btn-outline-{variant}:hover," )
                .Append( $".ant-btn-outline-{variant}:focus" )
                .Append( "{" )
                .Append( $"color: {hoverColor} !important;" )
                .Append( $"border-color: {hoverColor} !important;" )
                .AppendLine( "}" );

            sb.Append( $".ant-btn-outline-{variant}:hover > a:only-child," )
                .Append( $".ant-btn-outline-{variant}:focus > a:only-child" )
                .Append( "{" )
                .Append( "color: currentColor !important;" )
                .AppendLine( "}" );

            sb
                .Append( $".ant-btn-outline-{variant}:active," )
                .Append( $".ant-btn-outline-{variant}.active" )
                .Append( "{" )
                .Append( $"color: {activeColor} !important;" )
                .Append( $"border-color: {activeColor} !important;" )
                .AppendLine( "}" );

            sb
                .Append( $".ant-btn-outline-{variant}:active > a:only-child," )
                .Append( $".ant-btn-outline-{variant}.active > a:only-child" )
                .Append( "{" )
                .Append( "color: currentColor !important;" )
                .AppendLine( "}" );

            sb
                .Append( $".ant-btn-outline-{variant}-disabled," )
                .Append( $".ant-btn-outline-{variant}.disabled," )
                .Append( $".ant-btn-outline-{variant}[disabled]," )
                .Append( $".ant-btn-outline-{variant}-disabled:hover," )
                .Append( $".ant-btn-outline-{variant}.disabled:hover," )
                .Append( $".ant-btn-outline-{variant}[disabled]:hover," )
                .Append( $".ant-btn-outline-{variant}-disabled:focus," )
                .Append( $".ant-btn-outline-{variant}.disabled:focus," )
                .Append( $".ant-btn-outline-{variant}[disabled]:focus," )
                .Append( $".ant-btn-outline-{variant}-disabled:active," )
                .Append( $".ant-btn-outline-{variant}.disabled:active," )
                .Append( $".ant-btn-outline-{variant}[disabled]:active," )
                .Append( $".ant-btn-outline-{variant}-disabled.active," )
                .Append( $".ant-btn-outline-{variant}.disabled.active," )
                .Append( $".ant-btn-outline-{variant}[disabled].active" )
                .Append( $".btn-{variant}:disabled" )
                .Append( "{" )
                .Append( "color: rgba(0, 0, 0, 0.25) !important;" )
                .Append( "border-color: #d9d9d9 !important;" )
                .Append( "text-shadow: none !important;" )
                .AppendLine( "}" );

            sb
                .Append( $".ant-btn-outline-{variant}-disabled > a:only-child," )
                .Append( $".ant-btn-outline-{variant}.disabled > a:only-child," )
                .Append( $".ant-btn-outline-{variant}[disabled] > a:only-child," )
                .Append( $".ant-btn-outline-{variant}-disabled:hover > a:only-child," )
                .Append( $".ant-btn-outline-{variant}.disabled:hover > a:only-child," )
                .Append( $".ant-btn-outline-{variant}[disabled]:hover > a:only-child," )
                .Append( $".ant-btn-outline-{variant}-disabled:focus > a:only-child," )
                .Append( $".ant-btn-outline-{variant}.disabled:focus > a:only-child," )
                .Append( $".ant-btn-outline-{variant}[disabled]:focus > a:only-child," )
                .Append( $".ant-btn-outline-{variant}-disabled:active > a:only-child," )
                .Append( $".ant-btn-outline-{variant}.disabled:active > a:only-child," )
                .Append( $".ant-btn-outline-{variant}[disabled]:active > a:only-child," )
                .Append( $".ant-btn-outline-{variant}-disabled.active > a:only-child," )
                .Append( $".ant-btn-outline-{variant}.disabled.active > a:only-child," )
                .Append( $".ant-btn-outline-{variant}[disabled].active" )
                .Append( $".btn-{variant}:disabled" )
                .Append( "{" )
                .Append( "color: currentColor !important;" )
                .AppendLine( "}" );
        }

        protected override void GenerateButtonStyles( StringBuilder sb, Theme theme, ThemeButtonOptions options )
        {
            sb.Append( ".ant-btn" ).Append( "{" )
                .Append( $"border-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            sb.Append( ".ant-btn-sm" ).Append( "{" )
                .Append( $"border-radius: {GetBorderRadius( theme, options?.SmallBorderRadius, Var( ThemeVariables.BorderRadiusSmall ) )};" )
                .AppendLine( "}" );

            sb.Append( ".ant-btn-lg" ).Append( "{" )
                .Append( $"border-radius: {GetBorderRadius( theme, options?.LargeBorderRadius, Var( ThemeVariables.BorderRadiusLarge ) )};" )
                .AppendLine( "}" );

            if ( !string.IsNullOrEmpty( options?.Padding ) )
                sb.Append( ".ant-btn" ).Append( "{" )
                    .Append( $"padding: {options.Padding};" )
                    .AppendLine( "}" );

            if ( !string.IsNullOrEmpty( options?.Margin ) )
                sb.Append( ".ant-btn" ).Append( "{" )
                    .Append( $"margin: {options.Margin};" )
                    .AppendLine( "}" );

            if ( options?.DisabledOpacity != null )
                sb.Append( ".ant-btn[disabled]" ).Append( "{" )
                    .Append( $"color: rgba(0, 0, 0, {options.DisabledOpacity}) !important;" )
                    .AppendLine( "}" );
        }

        protected override void GenerateDropdownStyles( StringBuilder sb, Theme theme, ThemeDropdownOptions options )
        {
            sb.Append( ".ant-dropdown-menu" ).Append( "{" )
                .Append( $"border-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            if ( !string.IsNullOrEmpty( theme.ColorOptions?.Primary ) )
            {
                var backgroundColor = ParseColor( theme.ColorOptions.Primary );

                if ( !backgroundColor.IsEmpty )
                {
                    var background = ToHex( backgroundColor );

                    sb.Append( ".ant-dropdown-menu-item.active," )
                        .Append( ".ant-dropdown-menu-item:active" ).Append( "{" )
                        .Append( GetGradientBg( theme, background, options?.GradientBlendPercentage ) )
                        .AppendLine( "}" );
                }
            }
        }

        protected override void GenerateInputStyles( StringBuilder sb, Theme theme, ThemeInputOptions options )
        {
            sb.Append( ".ant-form-item input" ).Append( "{" )
                .Append( $"border-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            sb.Append( ".ant-input-group-addon:first-child" ).Append( "{" )
                .Append( $"border-top-left-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .Append( $"border-bottom-left-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            sb.Append( ".ant-input-group-addon:last-child" ).Append( "{" )
                .Append( $"border-top-right-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .Append( $"border-bottom-right-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            sb.Append( ".ant-select-selector, .ant-select-selector input" ).Append( "{" )
                .Append( $"border-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )} !important;" )
                .AppendLine( "}" );

            sb.Append( ".ant-checkbox-inner" ).Append( "{" )
                .Append( $"border-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            sb.Append( ".ant-upload button" ).Append( "{" )
                .Append( $"border-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            sb.Append( ".b-is-autocomplete.b-is-autocomplete-multipleselection" ).Append( "{" )
                .Append( $"border-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            if ( !string.IsNullOrEmpty( options?.Color ) )
            {
                sb.Append( ".ant-input" ).Append( "{" )
                    .Append( $"color: {options.Color};" )
                    .AppendLine( "}" );

                //sb.Append( $".input-group-text" ).Append( "{" )
                //    .Append( $"color: {options.Color};" )
                //    .AppendLine( "}" );

                sb.Append( ".ant-select-selection-search-input" ).Append( "{" )
                    .Append( $"color: {options.Color};" )
                    .AppendLine( "}" );
            }

            if ( !string.IsNullOrEmpty( options?.CheckColor ) )
            {
                GenerateInputCheckEditStyles( sb, theme, options );
            }

            if ( !string.IsNullOrEmpty( options?.SliderColor ) )
            {
                GenerateInputSliderStyles( sb, theme, options );
            }

            if ( !string.IsNullOrEmpty( theme.ColorOptions?.Primary ) )
            {
                sb
                    .Append( ".flatpickr-months .flatpickr-month:hover svg," )
                    .Append( ".flatpickr-months .flatpickr-next-month:hover svg," )
                    .Append( ".flatpickr-months .flatpickr-prev-month:hover svg" )
                    .Append( "{" )
                    .Append( $"fill: { Var( ThemeVariables.Color( "primary" ) )} !important;" )
                    .AppendLine( "}" );

                sb
                    .Append( ".flatpickr-day.selected, .flatpickr-day.startRange, .flatpickr-day.endRange, .flatpickr-day.selected.inRange, .flatpickr-day.startRange.inRange, .flatpickr-day.endRange.inRange, .flatpickr-day.selected:focus, .flatpickr-day.startRange:focus, .flatpickr-day.endRange:focus, .flatpickr-day.selected:hover, .flatpickr-day.startRange:hover, .flatpickr-day.endRange:hover, .flatpickr-day.selected.prevMonthDay, .flatpickr-day.startRange.prevMonthDay, .flatpickr-day.endRange.prevMonthDay, .flatpickr-day.selected.nextMonthDay, .flatpickr-day.startRange.nextMonthDay, .flatpickr-day.endRange.nextMonthDay" ).Append( "{" )
                    .Append( $"background: { Var( ThemeVariables.Color( "primary" ) )};" )
                    .Append( $"border-color: { Var( ThemeVariables.Color( "primary" ) )};" )
                    .AppendLine( "}" );

                sb
                    .Append( ".flatpickr-day:hover" ).Append( "{" )
                    .Append( $"background: { ToHex( Lighten( Var( ThemeVariables.Color( "primary" ) ), 90f ) )};" )
                    .AppendLine( "}" );

                sb
                    .Append( ".flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n+1)), .flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n+1)), .flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n+1))" ).Append( "{" )
                    .Append( $"box-shadow: -10px 0 0 { Var( ThemeVariables.Color( "primary" ) )};" )
                    .AppendLine( "}" );

                sb
                    .Append( ".flatpickr-day.today" ).Append( "{" )
                    .Append( $"border-color: { Var( ThemeVariables.Color( "primary" ) )};" )
                    .AppendLine( "}" );

                sb
                    .Append( ".flatpickr-day.today:hover" ).Append( "{" )
                    .Append( $"background: { Var( ThemeVariables.Color( "primary" ) )};" )
                    .Append( $"border-color: { Var( ThemeVariables.Color( "primary" ) )};" )
                    .AppendLine( "}" );

                sb
                    .Append( ".flatpickr-monthSelect-month:hover,.flatpickr-monthSelect-month:focus" ).Append( "{" )
                    .Append( $"background: { ToHex( Lighten( Var( ThemeVariables.Color( "primary" ) ), 90f ) )};" )
                    .AppendLine( "}" );

                sb
                    .Append( ".flatpickr-monthSelect-month.selected" ).Append( "{" )
                    .Append( $"background: { Var( ThemeVariables.Color( "primary" ) )};" )
                    .AppendLine( "}" );
            }
        }

        protected virtual void GenerateInputCheckEditStyles( StringBuilder sb, Theme theme, ThemeInputOptions options )
        {
            sb
                .Append( ".ant-checkbox-checked .ant-checkbox-inner" ).Append( "{" )
                .Append( $"background-color: {options.CheckColor};" )
                .Append( $"border-color: {options.CheckColor};" )
                .AppendLine( "}" );

            sb
                .Append( ".ant-radio-wrapper:hover .ant-radio," )
                .Append( ".ant-radio:hover .ant-radio-inner," )
                .Append( ".ant-radio-input:focus + .ant-radio-inner," )
                .Append( ".ant-radio-checked .ant-radio-inner" )
                .Append( "{" )
                .Append( $"border-color: {options.CheckColor};" )
                .AppendLine( "}" );

            sb
                .Append( ".ant-radio-inner::after" ).Append( "{" )
                .Append( $"background-color: {options.CheckColor};" )
                .AppendLine( "}" );

            sb
                .Append( ".ant-switch-checked" ).Append( "{" )
                .Append( $"background-color: {options.CheckColor};" )
                .AppendLine( "}" );
        }

        protected virtual void GenerateInputSliderStyles( StringBuilder sb, Theme theme, ThemeInputOptions options )
        {
            sb.Append( ".ant-slider-track" ).Append( "{" )
                .Append( $"background-color: {options.SliderColor};" )
                .AppendLine( "}" );

            sb.Append( ".ant-slider:hover .ant-slider-track" ).Append( "{" )
                .Append( $"background-color: {ToHex( Darken( options.SliderColor, 20f ) )};" )
                .AppendLine( "}" );

            sb.Append( ".ant-slider-handle" ).Append( "{" )
                .Append( $"border-color: {options.SliderColor};" )
                .AppendLine( "}" );

            sb
                .Append( ".ant-slider-handle:focus," )
                .Append( ".ant-slider:hover .ant-slider-handle:not(.ant-tooltip-open)" )
                .Append( "{" )
                .Append( $"border-color: {ToHex( Darken( options.SliderColor, 20f ) )};" )
                .AppendLine( "}" );
        }

        protected override void GenerateBadgeVariantStyles( StringBuilder sb, Theme theme, string variant, string inBackgroundColor )
        {
            var backgroundColor = ParseColor( inBackgroundColor );

            if ( backgroundColor.IsEmpty )
                return;

            var yiqBackgroundColor = Contrast( theme, backgroundColor );

            var background = ToHex( backgroundColor );
            var yiqBackground = ToHex( yiqBackgroundColor );

            sb.Append( $".ant-tag-{variant}" ).Append( "{" )
                .Append( $"color: {yiqBackground};" )
                .Append( $"background-color: {background};" )
                .AppendLine( "}" );
        }

        protected override void GenerateSwitchVariantStyles( StringBuilder sb, Theme theme, string variant, string inBackgroundColor, ThemeSwitchOptions options )
        {
            var backgroundColor = ParseColor( inBackgroundColor );

            if ( backgroundColor.IsEmpty )
                return;

            var boxShadowColor = Lighten( backgroundColor, options?.BoxShadowLightenColor ?? 25 );
            var disabledBackgroundColor = Lighten( backgroundColor, options?.DisabledLightenColor ?? 50 );

            var background = ToHex( backgroundColor );
            var boxShadow = ToHex( boxShadowColor );
            var disabledBackground = ToHex( disabledBackgroundColor );

            sb
                .Append( $".ant-switch.ant-switch-{variant}.ant-switch-checked" ).Append( "{" )
                .Append( $"background-color: {background};" )
                .AppendLine( "}" );

            sb
                .Append( $".ant-switch.ant-switch-{variant}:focus" ).Append( "{" )
                .Append( $"box-shadow: {boxShadow};" )
                .AppendLine( "}" );

            sb
                .Append( $".ant-switch:disabled.ant-switch-{variant}.ant-switch-checked" ).Append( "{" )
                .Append( $"background-color: {disabledBackground};" )
                .AppendLine( "}" );
        }

        protected override void GenerateStepsStyles( StringBuilder sb, Theme theme, ThemeStepsOptions stepsOptions )
        {
            sb
                .Append( ".ant-steps-item.ant-steps-item-active.ant-steps-item-process.ant-steps-item-finish .ant-steps-item-icon" ).Append( "{" )
                .Append( $"background-color: {Var( ThemeVariables.StepsItemIconActive, Var( ThemeVariables.Color( "primary" ) ) )};" )
                .AppendLine( "}" );

            sb
                .Append( ".ant-steps-item.ant-steps-item-active.ant-steps-item-process.ant-steps-item-finish .ant-steps-item-icon .ant-steps-icon" ).Append( "{" )
                .Append( $"color: {Var( ThemeVariables.StepsItemIconActiveYiq, Var( ThemeVariables.White ) )};" )
                .AppendLine( "}" );

            sb
                .Append( ".ant-steps-item.ant-steps-item-active.ant-steps-item-process .ant-steps-item-icon" ).Append( "{" )
                .Append( $"background: {Var( ThemeVariables.StepsItemIconActive, Var( ThemeVariables.Color( "primary" ) ) )};" )
                .Append( $"border-color: {Var( ThemeVariables.StepsItemIconActive, Var( ThemeVariables.Color( "primary" ) ) )};" )
                .AppendLine( "}" );
        }

        protected override void GenerateStepsVariantStyles( StringBuilder sb, Theme theme, string variant, string inBackgroundColor, ThemeStepsOptions stepsOptions )
        {
            sb
                .Append( $".ant-steps-item-{variant}.ant-steps-item-finish .ant-steps-item-content .ant-steps-item-title" ).Append( "{" )
                .Append( $"color: {Var( ThemeVariables.VariantStepsItemText( variant ) )};" )
                .AppendLine( "}" );

            sb
                .Append( $".ant-steps-item-{variant}.ant-steps-item-wait .ant-steps-item-icon" ).Append( "{" )
                .Append( $"border-color: {Var( ThemeVariables.VariantStepsItemIcon( variant ) )};" )
                .Append( $"color: {Var( ThemeVariables.VariantStepsItemIconYiq( variant ) )};" )
                .AppendLine( "}" );

            sb
                .Append( $".ant-steps-item-{variant}.ant-steps-item-wait .ant-steps-item-content .ant-steps-item-title" ).Append( "{" )
                .Append( $"color: {Var( ThemeVariables.VariantStepsItemText( variant ) )};" )
                .AppendLine( "}" );

            sb
                .Append( $".ant-steps-item-{variant}.ant-steps-item-active.ant-steps-item-finish .ant-steps-item-icon" ).Append( "{" )
                .Append( $"background-color: {Var( ThemeVariables.StepsItemIconActive, Var( ThemeVariables.Color( "primary" ) ) )};" )
                .Append( $"border-color: {Var( ThemeVariables.StepsItemIconActive, Var( ThemeVariables.Color( "primary" ) ) )};" )
                .Append( $"color: {Var( ThemeVariables.StepsItemIconActiveYiq, Var( ThemeVariables.White ) )};" )
                .AppendLine( "}" );

            sb
                .Append( $".ant-steps-item-{variant}.ant-steps-item-active.ant-steps-item-process .ant-steps-icon" ).Append( "{" )
                .Append( $"border-color: {Var( ThemeVariables.StepsItemIconActive, Var( ThemeVariables.Color( "primary" ) ) )};" )
                .Append( $"color: {Var( ThemeVariables.StepsItemIconActiveYiq, Var( ThemeVariables.White ) )};" )
                .AppendLine( "}" );

            sb
                .Append( $".ant-steps-item-{variant}.ant-steps-item-active.ant-steps-item-process .ant-steps-item-content .ant-steps-item-title" ).Append( "{" )
                .Append( $"color: {Var( ThemeVariables.VariantStepsItemIcon( variant ) )};" )
                .AppendLine( "}" );

            sb
                .Append( $".ant-steps-item-{variant} .ant-steps-item-icon" ).Append( "{" )
                .Append( $"border-color: {Var( ThemeVariables.VariantStepsItemIcon( variant ) )};" )
                .AppendLine( "}" );

            sb
                .Append( $".ant-steps-item-{variant} .ant-steps-item-icon .ant-steps-icon" ).Append( "{" )
                .Append( $"color: {Var( ThemeVariables.VariantStepsItemIcon( variant ) )};" )
                .AppendLine( "}" );

            sb
                .Append( $".ant-steps-item-{variant} .ant-steps-item-content .ant-steps-item-title" ).Append( "{" )
                .Append( $"color: {Var( ThemeVariables.VariantStepsItemText( variant ) )};" )
                .AppendLine( "}" );
        }

        protected override void GenerateRatingStyles( StringBuilder sb, Theme theme, ThemeRatingOptions ratingOptions )
        {
            if ( ratingOptions?.HoverOpacity != null )
            {
                sb
                    .Append( ".ant-rate .ant-rate-star.ant-rate-star-focused" ).Append( "{" )
                    .Append( $"opacity: {string.Format( CultureInfo.InvariantCulture, "{0:F1}", ratingOptions.HoverOpacity )};" )
                    .AppendLine( "}" );
            }
        }

        protected override void GenerateRatingVariantStyles( StringBuilder sb, Theme theme, string variant, string inBackgroundColor, ThemeRatingOptions ratingOptions )
        {
            sb
                .Append( $".ant-rate .ant-rate-star.ant-rate-star-{variant}" ).Append( "{" )
                .Append( $"color: {Var( ThemeVariables.VariantRatingColor( variant ) )};" )
                .AppendLine( "}" );
        }

        protected override void GenerateAlertVariantStyles( StringBuilder sb, Theme theme, string variant, string inBackgroundColor, string inBorderColor, string inColor, ThemeAlertOptions options )
        {
            var backgroundColor = ParseColor( inBackgroundColor );
            var borderColor = ParseColor( inBorderColor );
            var textColor = ParseColor( inColor );

            var alertLinkColor = Darken( textColor, 10f );

            var background = ToHex( backgroundColor );
            var border = ToHex( borderColor );
            var text = ToHex( textColor );
            var alertLink = ToHex( alertLinkColor );

            sb.Append( $".ant-alert-{variant}" ).Append( "{" )
                .Append( $"color: {text};" )
                .Append( GetGradientBg( theme, background, options?.GradientBlendPercentage ) )
                .Append( $"border-color: {border};" )
                .AppendLine( "}" );

            sb.Append( $".ant-alert-{variant}.alert-link" ).Append( "{" )
                .Append( $"color: {alertLink};" )
                .AppendLine( "}" );
        }

        protected override void GenerateTableVariantStyles( StringBuilder sb, Theme theme, string variant, string inBackgroundColor, string inBorderColor )
        {
            var backgroundColor = ParseColor( inBackgroundColor );
            var hoverBackgroundColor = Darken( backgroundColor, 5 );
            var borderColor = ParseColor( inBorderColor );

            var background = ToHex( backgroundColor );
            var hoverBackground = ToHex( hoverBackgroundColor );
            var border = ToHex( borderColor );

            sb.Append( $".ant-table-{variant}," )
                .Append( $".ant-table-{variant}>th," )
                .Append( $".ant-table-{variant}>td" )
                .Append( "{" )
                .Append( $"background-color: {background};" )
                .AppendLine( "}" );

            sb.Append( $".ant-table-{variant} th," )
                .Append( $".ant-table-{variant} td," )
                .Append( $".ant-table-{variant} thead td," )
                .Append( $".ant-table-{variant} tbody + tbody" )
                .Append( "{" )
                .Append( $"border-color: {border};" )
                .AppendLine( "}" );

            sb.Append( $".ant-table-hover .ant-table-{variant}:hover" )
                .Append( "{" )
                .Append( $"background-color: {hoverBackground};" )
                .AppendLine( "}" );

            sb.Append( $".ant-table-hover .ant-table-{variant}:hover>td" )
                .Append( $".ant-table-hover .ant-table-{variant}:hover>th" )
                .Append( "{" )
                .Append( $"background-color: {hoverBackground};" )
                .AppendLine( "}" );
        }

        protected override void GenerateCardStyles( StringBuilder sb, Theme theme, ThemeCardOptions options )
        {
            sb.Append( ".ant-card" ).Append( "{" )
                .Append( $"border-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            sb.Append( ".ant-card-cover:first-child" ).Append( "{" )
                .Append( $"border-top-left-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .Append( $"border-top-right-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            sb.Append( ".ant-card-cover:last-child" ).Append( "{" )
                .Append( $"border-bottom-left-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .Append( $"border-bottom-right-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            if ( !string.IsNullOrEmpty( options?.ImageTopRadius ) )
                sb.Append( ".ant-card-cover" ).Append( "{" )
                    .Append( $"border-top-left-radius: {options.ImageTopRadius};" )
                    .Append( $"border-top-right-radius: {options.ImageTopRadius};" )
                    .AppendLine( "}" );
        }

        protected override void GenerateModalStyles( StringBuilder sb, Theme theme, ThemeModalOptions options )
        {
            sb.Append( ".modal-content" ).Append( "{" )
                .Append( $"border-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );
        }

        protected override void GenerateTabsStyles( StringBuilder sb, Theme theme, ThemeTabsOptions options )
        {
            sb.Append( ".ant-tabs .ant-tabs-tab" ).Append( "{" )
                .Append( $"border-top-left-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .Append( $"border-top-right-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            sb.Append( ".ant-tabs-pills .ant-tabs-nav .ant-tabs-tab" ).Append( "{" )
                .Append( $"border-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            if ( !string.IsNullOrEmpty( theme.ColorOptions?.Primary ) )
            {
                sb
                    .Append( ".ant-tabs-pills .ant-tabs-nav .ant-tabs-tab-active" )
                    .Append( "{" )
                    .Append( $"color: {Var( ThemeVariables.White )};" )
                    .Append( $"background-color: {Var( ThemeVariables.Color( "primary" ) )};" )
                    .AppendLine( "}" );

                sb
                    .Append( ".ant-tabs-nav .ant-tabs-tab:active," )
                    .Append( ".ant-tabs-nav .ant-tabs-tab-active" )
                    .Append( "{" )
                    .Append( $"color: {Var( ThemeVariables.Color( "primary" ) )};" )
                    .AppendLine( "}" );

                var hoverColor = ToHex( Lighten( Var( ThemeVariables.Color( "primary" ) ), 20f ) );

                sb
                    .Append( ".ant-tabs-nav .ant-tabs-tab:hover" )
                    .Append( "{" )
                    .Append( $"color: {hoverColor};" )
                    .AppendLine( "}" );
            }
        }

        protected override void GenerateProgressStyles( StringBuilder sb, Theme theme, ThemeProgressOptions options )
        {
            sb
                .Append( ".ant-progress-inner," )
                .Append( ".ant-progress-bg" )
                .Append( "{" )
                .Append( $"border-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            if ( !string.IsNullOrEmpty( theme.ColorOptions?.Primary ) )
            {
                sb.Append( ".ant-progress-bg" ).Append( "{" )
                    .Append( $"background-color: {Var( ThemeVariables.Color( "primary" ) )};" )
                    .AppendLine( "}" );
            }

            base.GenerateProgressStyles( sb, theme, options );
        }

        protected override void GenerateAlertStyles( StringBuilder sb, Theme theme, ThemeAlertOptions options )
        {
            sb.Append( ".ant-alert" ).Append( "{" )
                .Append( $"border-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );
        }

        protected override void GenerateBreadcrumbStyles( StringBuilder sb, Theme theme, ThemeBreadcrumbOptions options )
        {
            sb.Append( ".ant-breadcrumb" ).Append( "{" )
                .Append( $"border-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );


            if ( !string.IsNullOrEmpty( Var( ThemeVariables.BreadcrumbColor ) ) )
            {
                sb.Append( ".ant-breadcrumb-link>a" ).Append( "{" )
                    .Append( $"color: {Var( ThemeVariables.BreadcrumbColor )};" )
                    .AppendLine( "}" );
            }
        }

        protected override void GenerateBadgeStyles( StringBuilder sb, Theme theme, ThemeBadgeOptions options )
        {
            sb.Append( ".ant-tag:not(.ant-tag-pill)" ).Append( "{" )
                .Append( $"border-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );
        }

        protected override void GeneratePaginationStyles( StringBuilder sb, Theme theme, ThemePaginationOptions options )
        {
            sb.Append( ".ant-pagination-item:first-child .ant-pagination-link" ).Append( "{" )
                .Append( $"border-top-left-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .Append( $"border-bottom-left-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            sb.Append( ".ant-pagination-item:last-child .ant-pagination-link" ).Append( "{" )
                .Append( $"border-top-right-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .Append( $"border-bottom-right-radius: {GetBorderRadius( theme, options?.BorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            sb.Append( ".ant-pagination-lg .ant-pagination-item:first-child .ant-pagination-link" ).Append( "{" )
                .Append( $"border-top-left-radius: {GetBorderRadius( theme, options?.LargeBorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .Append( $"border-bottom-left-radius: {GetBorderRadius( theme, options?.LargeBorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            sb.Append( ".ant-pagination-lg .ant-pagination-item:last-child .ant-pagination-link" ).Append( "{" )
                .Append( $"border-top-right-radius: {GetBorderRadius( theme, options?.LargeBorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .Append( $"border-bottom-right-radius: {GetBorderRadius( theme, options?.LargeBorderRadius, Var( ThemeVariables.BorderRadius ) )};" )
                .AppendLine( "}" );

            if ( !string.IsNullOrEmpty( theme.ColorOptions?.Primary ) )
            {
                var color = theme.ColorOptions.Primary;

                sb
                    .Append( ".ant-pagination-item:focus," )
                    .Append( ".ant-pagination-item:hover" )
                    .Append( "{" )
                    .Append( $"border-color: {color};" )
                    .AppendLine( "}" );

                sb
                    .Append( ".ant-pagination-item:focus a," )
                    .Append( ".ant-pagination-item:hover a" )
                    .Append( "{" )
                    .Append( $"color: {color};" )
                    .AppendLine( "}" );

                sb
                    .Append( ".ant-pagination-item-active" )
                    .Append( "{" )
                    .Append( $"border-color: {color};" )
                    .AppendLine( "}" );

                sb.Append( ".ant-pagination-item-active a" )
                    .Append( "{" )
                    .Append( $"color: {color};" )
                    .AppendLine( "}" );

                var hoverColor = ToHex( Lighten( color, 40f ) );

                sb
                    .Append( ".ant-pagination-item-active:focus," )
                    .Append( ".ant-pagination-item-active:hover" )
                    .Append( "{" )
                    .Append( $"border-color: {hoverColor};" )
                    .AppendLine( "}" );

                sb
                    .Append( ".ant-pagination-item-active:focus a," )
                    .Append( ".ant-pagination-item-active:hover a" )
                    .Append( "{" )
                    .Append( $"color: {hoverColor};" )
                    .AppendLine( "}" );
            }
        }

        protected override void GenerateBarStyles( StringBuilder sb, Theme theme, ThemeBarOptions options )
        {
            foreach ( var (variant, _) in theme.ValidBackgroundColors )
            {
                var yiqColor = Var( ThemeVariables.BackgroundYiqColor( variant ) );

                if ( string.IsNullOrEmpty( yiqColor ) )
                    continue;

                sb
                    .Append( $".ant-menu.bg-{variant} .ant-menu-item .ant-menu-link," )
                    .Append( $".ant-menu.bg-{variant} .ant-menu-item .ant-menu-submenu-title span" )
                    .Append( "{" )
                    .Append( $"color: {yiqColor};" )
                    .AppendLine( "}" );
            }
        }

        protected override void GenerateParagraphVariantStyles( StringBuilder sb, Theme theme, string variant, string inTextColor )
        {
            var textColor = variant == "body" && !string.IsNullOrEmpty( theme.BodyOptions?.TextColor )
                ? ParseColor( theme.BodyOptions.TextColor )
                : ParseColor( inTextColor );

            var hexTextColor = ToHex( textColor );

            sb.Append( $".ant-typography-{variant}" )
                .Append( "{" )
                .Append( $"color: {hexTextColor};" )
                .AppendLine( "}" );
        }

        protected override void GenerateInputVariantStyles( StringBuilder sb, Theme theme, string variant, string inColor )
        {
            var color = ToHex( ParseColor( inColor ) );

            sb
                .Append( $".ant-input.ant-form-text-{variant}," )
                .Append( $".ant-form-text.ant-form-text-{variant}" )
                .Append( "{" )
                .Append( $"color: {color};" )
                .AppendLine( "}" );
        }

        protected override void GenerateListGroupItemStyles( StringBuilder sb, Theme theme, ThemeListGroupItemOptions options )
        {
            if ( !string.IsNullOrEmpty( theme.ColorOptions?.Primary ) )
            {
                var white = Var( ThemeVariables.White );
                var primary = Var( ThemeVariables.Color( "primary" ) );

                sb
                    .Append( ".ant-list-item.active" )
                    .Append( "{" )
                    .Append( $"color: {white};" )
                    .Append( GetGradientBg( theme, primary, options?.GradientBlendPercentage ) )
                    .Append( $"border-color: {primary};" )
                    .AppendLine( "}" );
            }
        }

        protected override void GenerateListGroupItemVariantStyles( StringBuilder sb, Theme theme, string variant, string inBackgroundColor, string inColor, ThemeListGroupItemOptions options )
        {
            var backgroundColor = ParseColor( inBackgroundColor );
            var textColor = ParseColor( inColor );

            var background = ToHex( backgroundColor );
            var text = ToHex( textColor );

            sb.Append( $".ant-list .ant-list-items > .ant-list-item.ant-list-item-{variant}" ).Append( "{" )
                .Append( $"color: {text};" )
                .Append( GetGradientBg( theme, background, options?.GradientBlendPercentage ) )
                .AppendLine( "}" );

            sb
                .Append( $".ant-list .ant-list-items > .ant-list-item.ant-list-item-{variant}.ant-list-item-actionable:hover," )
                .Append( $".ant-list .ant-list-items > .ant-list-item.ant-list-item-{variant}.ant-list-item-actionable:focus" )
                .Append( "{" )
                .Append( $"color: {text};" )
                .Append( ToHex( Darken( GetGradientBg( theme, background, options?.GradientBlendPercentage ), 5 ) ) )
                .AppendLine( "}" );

            sb
                .Append( $".ant-list .ant-list-items > .ant-list-item.ant-list-item-{variant}.ant-list-item-actionable.active" )
                .Append( "{" )
                .Append( "color: #fff;" )
                .Append( $"background-color: {text};" )
                .Append( $"border-color: {text};" )
                .AppendLine( "}" );
        }

        private static string GetValidBreakpointName( string name ) => name switch
        {
            "mobile" => "xs",
            "tablet" => "sm",
            "desktop" => "md",
            "widescreen" => "lg",
            "fullhd" => "xl",
            _ => "",
        };

        protected override void GenerateSpacingStyles( StringBuilder sb, Theme theme, ThemeSpacingOptions options )
        {
            if ( theme.BreakpointOptions == null || options == null )
                return;

            foreach ( var breakpoint in theme.BreakpointOptions )
            {
                var breakpointName = GetValidBreakpointName( breakpoint.Key );
                var breakpointMin = breakpoint.Value();

                var hasMinMedia = !string.IsNullOrEmpty( breakpointMin ) && breakpointMin != "0";

                if ( hasMinMedia )
                {
                    sb.Append( $"@media (min-width: {breakpointMin})" ).Append( "{" );
                }

                var infix = string.IsNullOrEmpty( breakpointMin ) || breakpointMin == "0"
                    ? ""
                    : $"-{breakpointName}";

                foreach ( (string prop, string abbrev) in new[] { ("margin", "m"), ("padding", "p") } )
                {
                    foreach ( (string size, Func<string> lenghtFunc) in options )
                    {
                        var length = lenghtFunc.Invoke();

                        sb
                            .Append( $".{abbrev}{infix}-{size}" )
                            .Append( "{" ).Append( $"{prop}: {length} !important;" ).Append( "}" );

                        sb
                            .Append( $".{abbrev}t{infix}-{size}," )
                            .Append( $".{abbrev}y{infix}-{size}" )
                            .Append( "{" ).Append( $"{prop}-top: {length} !important;" ).Append( "}" );

                        sb
                            .Append( $".{abbrev}r{infix}-{size}," )
                            .Append( $".{abbrev}x{infix}-{size}" )
                            .Append( "{" ).Append( $"{prop}-right: {length} !important;" ).Append( "}" );

                        sb
                            .Append( $".{abbrev}b{infix}-{size}," )
                            .Append( $".{abbrev}y{infix}-{size}" )
                            .Append( "{" ).Append( $"{prop}-bottom: {length} !important;" ).Append( "}" );

                        sb
                            .Append( $".{abbrev}l{infix}-{size}," )
                            .Append( $".{abbrev}x{infix}-{size}" )
                            .Append( "{" ).Append( $"{prop}-left: {length} !important;" ).Append( "}" );
                    }
                }

                foreach ( (string size, Func<string> lenghtFunc) in options )
                {
                    if ( string.IsNullOrEmpty( size ) || size == "0" )
                        continue;

                    var length = lenghtFunc.Invoke();

                    sb
                        .Append( $".m{infix}-n{size}" )
                        .Append( "{" ).Append( $"margin: -{length} !important;" ).Append( "}" );

                    sb
                        .Append( $".mt{infix}-n{size}," )
                        .Append( $".my{infix}-n{size}" )
                        .Append( "{" ).Append( $"margin-top: -{length} !important;" ).Append( "}" );

                    sb
                        .Append( $".mr{infix}-n{size}," )
                        .Append( $".mx{infix}-n{size}" )
                        .Append( "{" ).Append( $"margin-right: -{length} !important;" ).Append( "}" );

                    sb
                        .Append( $".mb{infix}-n{size}," )
                        .Append( $".my{infix}-n{size}" )
                        .Append( "{" ).Append( $"margin-bottom: -{length} !important;" ).Append( "}" );

                    sb
                        .Append( $".ml{infix}-n{size}," )
                        .Append( $".mx{infix}-n{size}" )
                        .Append( "{" ).Append( $"margin-left: -{length} !important;" ).Append( "}" );
                }

                if ( hasMinMedia )
                {
                    sb.Append( "}" );
                }
            }
        }

        #endregion
    }
}
